import React from 'react';
import { useDrag } from 'react-dnd';
import { message } from 'antd';
import { connect } from 'dva';
import classNames from 'classnames';
import findLastIndex from 'lodash/findLastIndex';
import some from 'lodash/some';
import get from 'lodash/get';
import { getUniqueID } from '@/utils/utils';
import { getLevel, $$splice, $$set, getNode, hasThisName } from './utils';
import { itemTypes, bowlTypes } from './types';
import styles from '../styles.less';

/**
 * 这4个属性type, level, label, componentType 都是调用时通过标签属性传入
 *
 * 从Left组件 拖拽时 level === undefined
 *
 */
const DragItem = ({ type, level, children, dispatch, formSchema, ...rest }) => {
  const box = { type, level, ...rest };
  const [{ isDragging }, drag] = useDrag({
    // item 中包含 index 属性，则在 drop 组件 hover 和 drop 是可以根据第一个参数获取到 index 值
    item: box,

    /**
     *  拖拽开始时触发。
     * react-dnd约定，begin必须返回一个包含type的对象，否则报错
     */
    begin() {
      // __id= 'holder' 表示是占位的
      const hasHolder = getLevel(formSchema, { __id: 'holder' }) !== -1;

      // 已存在，或者不是从Left拖拽出来的组件，直接return
      if (hasHolder || level !== undefined) {
        return box;
      }

      //  bowl类型：在树的第一层的最后一位插入，如果占位元素已经存在，不再重复插入
      if (type === itemTypes.bowl) {
        dispatch({
          type: 'formDesigner/updateFormSchema',
          payload: $$set(formSchema, formSchema.length, {
            componentType: 'Card',
            __id: 'holder',
            label: rest.label,
            name: '',
            properties: [],
          }),
        });
      }

      //  block类型：在树的第一层的最后一位插入，如果占位元素已经存在，不再重复插入
      if (type === itemTypes.block || type === itemTypes.staticBlock) {
        dispatch({
          type: 'formDesigner/updateFormSchema',
          payload: $$set(formSchema, formSchema.length, {
            componentType: rest.componentType,
            __id: 'holder',
            label: rest.label,
          }),
        });
      }

      // food类型：在树的第一层找到排在最后面的bowl类型,并在这个bowl组件的最后一个子节点后面，插入当前类型的food元素
      if (type === itemTypes.food && formSchema.length > 0) {
        const lastIndex = findLastIndex(formSchema, item =>
          some(bowlTypes, val => val.componentType === item.componentType)
        );

        if (lastIndex !== -1) {
          dispatch({
            type: 'formDesigner/updateFormSchema',
            payload: $$set(formSchema, `${lastIndex}-${formSchema[lastIndex].properties.length}`, {
              ...rest,
              __id: 'holder',
              name: getUniqueID(`holder`),
            }),
          });
        }
      }

      return box;
    },
    /**
     *  拖拽结束时触发（即松开鼠标drop）
     */
    end(_, monitor) {
      const holderLevel = getLevel(formSchema, { __id: 'holder' });
      const item = monitor.getItem();

      /**
       *  拖入画布并结束时，判断是否将拖拽元素放入了目标接收组件中
       *  1、如果是，则使用真正传入的 box 元素代替占位元素
       *  2、如果否，则将占位元素删除
       *
       *  monitor.didDrop() 返回true 表示拖拽的元素已经被drop容器接收
       */
      if (monitor.didDrop()) {
        // 不允许画布中的表单元素的name重复
        if (hasThisName(formSchema, rest)) {
          // 表单元素name重复
          message.warning('重复添加');

          if (holderLevel !== -1) {
            dispatch({
              type: 'formDesigner/removeItem',
              payload: {
                level: holderLevel,
              },
            });
          }

          return;
        }

        let raw = [];

        const insertItem = {
          name: getUniqueID(`${item.componentType}_name`),
          ...rest,
          __id: getUniqueID('el'), // 重置，避免id重复
        };

        // 防止card组件没有properties引起SlickForm渲染时报错
        // IMPROVE: 拖拽card组件不带子节点
        if (item.componentType === 'Card' && !Array.isArray(get(rest, 'properties'))) {
          insertItem.properties = [];
        }

        // TODO : card只允许添加相同业务属性的组件

        if (item.type === itemTypes.food) {
          const ab = holderLevel.split('-');
          let parentLevel = '';
          ab.pop();

          if (ab.length === 0) {
            parentLevel = `${holderLevel.split('-')[0]}`;
          } else {
            parentLevel = `${ab.join('-')}`;
          }
          const parentNode = getNode(formSchema, parentLevel);
          if (!parentNode || `${parentNode.busiObjId}` !== `${insertItem.busiObjId}`) {
            message.warning('只接收相同业务属性的字段');
            dispatch({
              type: 'formDesigner/removeItem',
              payload: {
                level: holderLevel,
              },
            });
            return;
          }
        }

        if (holderLevel !== -1) {
          raw = $$splice(formSchema, holderLevel, insertItem);
        }

        dispatch({
          type: 'formDesigner/updateFormSchema',
          payload: raw,
        });
      } else {
        message.warning('基础组件只能放在容器组件中');

        if (holderLevel !== -1) {
          dispatch({
            type: 'formDesigner/removeItem',
            payload: {
              level: holderLevel,
            },
          });
        }
      }
    },

    collect: monitor => ({
      isDragging: monitor.isDragging(),
      // canDrag: monitor.canDrag(),
    }),
  });

  return (
    <div ref={drag} className={classNames(styles.dragItem, { isDragging })}>
      {/* id是否为undefined区分 防止从left拖拽food时 底色变红 */}
      {/* {isDragging && id !== undefined ? (
        <div className={classNames(styles.mask, styles.move)} />
      ) : null}
      {id === 'holder' ? <div className={classNames(styles.mask, styles.holder)} /> : null} */}
      {children}
    </div>
  );
};

export default connect(({ formDesigner }) => ({
  formSchema: formDesigner.formSchema,
}))(DragItem);
